package factory

import (
	"bytes"
	"strconv"
)

const (
	EMPTY_STRING      string = ""
	QUOTECHR                 = '"'
	CHAR_QUOTE_DOUBLE        = '"'
	CHAR_QUOTE_SINGLE        = '\''
	CHAR_SLASH               = '\\'
)

func EscapeChar(c byte) byte {
	switch c {
	case 't':
		return '\t'
	default:
		return c
	}
}

func StrToIntDef(s string, defval int) int {
	v, err := strconv.ParseInt(s, 10, 64)
	if err != nil {
		return defval
	} else {
		return int(v)
	}
}

// $1 spidx   ' ' 3, tokens[2] = " "
func ParseTokens(s string, sep byte) (tokens []string) {

	var eMarker byte = 0
	var tmp bytes.Buffer
	var slashFlag bool

	var nextFunc func(c byte)

	var nextForQuote = func(c byte) {
		if c == eMarker {
			tokens = append(tokens, tmp.String())
			tmp.Reset()
			nextFunc = nil
		} else {
			tmp.WriteByte(c)
		}
		return
	}

	for i := 0; i < len(s); {
		c := s[i]

		if slashFlag {
			tmp.WriteByte(EscapeChar(c))
			i++
			slashFlag = false
			continue
		}

		if c == CHAR_SLASH {
			slashFlag = true
			i++
			continue
		}

		if nextFunc != nil {
			nextFunc(c)
			i++
			continue
		}

		switch c {
		case sep:
			if tmp.Len() > 0 {
				tokens = append(tokens, tmp.String())
				tmp.Reset()
			}
			i++
			continue
		case CHAR_QUOTE_DOUBLE:
			eMarker = CHAR_QUOTE_DOUBLE
			nextFunc = nextForQuote
			i++
			continue
		case CHAR_QUOTE_SINGLE:
			eMarker = CHAR_QUOTE_SINGLE
			nextFunc = nextForQuote
			i++
			continue
		default:
			tmp.WriteByte(c)
			i++
		}
	}

	if tmp.Len() > 0 {
		tokens = append(tokens, tmp.String())
	}
	return
}
